/**
 * Created by rirong on 14-12-18.
 */

"use strict";

var  DataGo = require('./DataCenterGo')
	,DataCenterGo = DataGo.base
	,isMetric = DataGo.isMetric
	,radon = require('radon')
	,include = radon.use('Include')
	,util = radon.util
	,sysUtil = require('util')
	,config = DataGo.config
	,DataCenterParam = require('./DataCenterParam').base
	,MongoCriteria = require('./MongoCriteria').base;

var hawkConfig = radon.config('hawk') || {'user_id_field': '_id','user_model': 'DspUser'};
var idField = hawkConfig.user_id_field;
var generator = util.generator;

var CONST = {
	'USER_TYPE_EMPLOYEE': 3
	,'SUPER_ID': -1
	,'INCLUDE_MONGO_FIELDS': 1
	,'INCLUDE_METRIC_FIELDS': 2
};

function getMongoRegx(name, space, flag) {
	if(space === undefined) {
		space = ' ';
	}
	if(flag === undefined) {
		flag = 'i';
	}

	name = name.replace(/([$^|*+\-.{}\\\[\]\(\)])/g, '\\$1');
	var ns = name.trim().split(new RegExp('['+ space +']+', 'g'));
	return new RegExp('(' + ns.join('|') + ')', flag);
}

function DataCenterHelper(type, reqData, goParam) {
	this.PARAM = new DataCenterParam(type);
	this.$type = type;	//查询的数据类型. todo 待补充
	this.$fields = [];	// 查询的字段
	this.$excludeFields = [];	//要排除的字段
	this.$errorCode = 0; //错误码
	this.$errorData = null;//错误信息
	this.$dimCond = {};//维度条件
	this.$addOnCond = {};//与条件
	this.$dataCenterGo = new DataCenterGo(goParam);

	this.get = util.getValue.bind(util, reqData);
}
exports.base = DataCenterHelper;

//获取静态变量的值.
for (var key in CONST){
	if(CONST.hasOwnProperty(key)) {
		DataCenterHelper[key] = CONST[key];
	}
}

DataCenterHelper.prototype.getOptions = function(isExport) {
	if(this.$fields && this.$fields.length) {
		this.PARAM.fields(this.$fields);

		// todo 以前有的读就放开, 暂时node 未支持.
		//switch (include.getUser().type()) {
		//	case 4: break;
		//	case 1:
		//		this.excludeFields('{cost_true}');
		//		break;
		//	default :
		//		this.excludeFields('{cost_true},{cost_proxy}');
		//}
	}

	this.PARAM.excludeFields(this.$excludeFields);
	return this.PARAM.getOptions(isExport);
};

/**
 * 过滤关键字记录
 * @param  [string]或者string $field_name Mongo数据字段名称, 默认为 Name
 * @param  string $param_name 请求参数名称, 默认为 Word
 * @return Object             返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.filterWord = function(fieldName, paramName) {
	if(fieldName === undefined) {
		fieldName = 'Name';
	}
	var word = this.get(paramName || 'word','', 'trim');
	var filedCond = [];
	if(word) {
		if(!Array.isArray(fieldName)) {
			fieldName = [fieldName];
		}

		//普通关键字过滤
		var regx = getMongoRegx(word);
		fieldName.forEach(function(field) {
			var query = {};
			query[field] = regx;
			filedCond.push(query)
		});

		// 匹配数字关系
		var ids = getParamIds.call(this, paramName || 'word', ' ');
		if(ids && ids.length) {
			var tmp = {};
			tmp[idField] = ids.length === 1 ? ids[0] : {'$in': ids};
			filedCond.push(tmp);
			filedCond.push({
				_id: ids.length === 1 ? ids[0] : {'$in': ids}
			});
		}

		if(filedCond.length === 1) {
			var key = Object.keys(filedCond[0]);
			this.PARAM.addAnd(key[0], filedCond[0][key[0]]);
		}
		else if(filedCond.length){
			this.PARAM.addOr(filedCond);
		}
	}

	return this;
};

/**
 * 过滤多关键字记录
 * @param  string $field_name Mongo数据字段名称, 默认为 Name
 * @param  string $param_name 请求参数名称, 默认为 Words
 * @return Object             返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.filterWords = function(fieldName, paramName) {
	if(fieldName === undefined) {
		fieldName = 'Name';
	}
	var word = this.get(paramName || 'words', '', 'trim');
	var filedCond = [];
	if(word) {
		if(!Array.isArray(fieldName)) {
			fieldName = [fieldName];
		}

		//普通关键字过滤
		var regx = getMongoRegx(word, ',');
		fieldName.forEach(function(field) {
			var query = {};
			query[field] = regx;
			filedCond.push(query)
		});

		// 匹配数字关系
		var ids = getParamIds.call(this, paramName || 'words');
		if(ids && ids.length) {
			var tmp = {};
			tmp[idField] = ids.length === 1 ? ids[0] : {'$in': ids};
			filedCond.push(tmp);
			filedCond.push({
				_id: ids.length === 1 ? ids[0] : {'$in': ids}
			})
		}

		if(filedCond.length === 1) {
			var key = Object.keys(filedCond[0]);
			this.PARAM.addAnd(key[0], filedCond[0][key[0]]);
		}
		else if(filedCond.length){
			this.PARAM.addOr(filedCond);
		}
	}

	return this;
};

/**
 * 过滤指标参数过滤条件
 * @param  string $param_name 请求参数名称，默认为 metrics_filter
 * @return Object             返回当前数据中心对象供链式调用
 */

DataCenterHelper.prototype.filterMetrics = function(value) {
	var param = this.get(value || 'metrics_filter');
	if(sysUtil.isString(param)) {
		try {
			param = JSON.parse(param);
		}
		catch(e) {}
	}
	var where;
	if(param && Array.isArray(param) && param.length) {
		var formats = config('formats');
		param.forEach(function(item) {
			var con;
			var name = item['factor'];
			var val = +item['value'];
			// 比率指标值先转换为小数
			if(formats[name] && formats[name] == 'rate') {
				val /= 100;
			}

			// 判断有效的比较符号
			switch (item['sign']) {
				case '=':
					break;
				case '<':
					val = {'$lt': val};
					break;
				case '>':
					val = {'$gt': val};
					break;
				default :
					con = true;
			}

			if(!con) {
				if(!where) {
					where = {};
				}
				where[name] = val;
			}
		});

		// 设置指标查询条件
		if(where) {
			this.PARAM.addCond(where);
		}
	}

	return this;

};

/**
 * 过滤记录ID参数
 * @param  string $id_name  单ID参数名称, 默认为 Id
 * @param  string $ids_name 多ID参数名称, 默认为 Ids
 * @return Object           返回当前数据中心对象供链式调用
 */

DataCenterHelper.prototype.filterId = function(idName, idsName) {
	var id = this.get(idName || 'Id', 0, 'int');

	if(id > 0) {
		this.PARAM.addAnd('_id', id);
	}

	var ids = getParamIds.call(this, idName || 'ids');
	if(ids && ids.length) {
		this.PARAM.addAnd('_id', '$in', ids);
	}

	return this;
};

/**
 * 过滤记录删除状态
 * @return Object 返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.filterDeleted = function(fieldName, paramName) {
	var val = this.get(paramName || 'IsDeleted', 0, 'int');
	if (!fieldName){
		fieldName = 'IsDeleted';
	}
	switch(val){
		case 'true':
		case true:
		case 1:
			this.PARAM.addAnd(fieldName, true);
			break;
		case 0:
		case false:
		case 'false':
			this.PARAM.addAnd(fieldName, false);
			break;
		case -1:
			break;
		default:
			this.PARAM.addAnd(fieldName, false);
			break;
	}
	return this;
};


/**
 * 过滤记录创建时间段
 * @return Object 返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.filterCreateTime = function(beginName, endName) {
	var cond;
	var begin  = this.get(beginName || 'BeginCreate', 0);
	if(begin && (begin = toDateStamp.call(this, begin))) {
		cond = {
			'$gte': begin
		};
	}
	var end = this.get(endName || 'EndCreate', 0);
	if(end) {
		if(!cond) {
			cond = {};
		}
		cond['$lte'] = end;
	}
	if(cond) {
		this.PARAM.addAnd('CreateTime', cond);
	}

	return this;
};


/**
 * 过滤查询字段
 * @param  Mix    $fields     <可选> 指定查询的字段, 逗号分隔字符串或数组, 默认为从参数中读取
 * @param  string $param_name <可选> 查询字段参数变量名, 默认为 MFields
 * @return Object             返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.filterFields = function(value, name) {
	if(!name) {
		name = 'Fields';
	}
	if(!value) {
		value = this.get(name);
	}

	if(sysUtil.isString(value)) {
		value = value.trim().split(',');
	}

	this.$fields = value;

	return this;
};

/*
 过滤Mongo字段项.
 value true 时就调用配置的默认fields 字段(默认的情况)
 value false 时就只返回_id 的mongo字段.
 value ['c','b'] 或者 'c,b' 只返回 c b 的mongo 字段.
 */
DataCenterHelper.prototype.filterMongoFields = function(value, name) {
	if(!value) {
		value = this.get(name || 'mongoField', true);
	}

	this.PARAM.mongoField(value);
	return this;
};


DataCenterHelper.prototype.filterCostFields = function() {
	/* 一切由前端决定
	switch (include.getUser().type()) {
		case 1:// 如果是代理用户, 只增加代理价格
			this.addFields('{cost_proxy}');
			break;
		case 4:// 如果是超级用户, 增加所有价格分组
			this.addFields('{cost_proxy},{cost_proxy}');
			break;
	}
	*/

	return this;
};

/**
 * 附加查询字段到返回字段参数中
 * @param Array   $fields 要添加的查询字段数组
 * @return Object         返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.addFields = function(value) {
	if(value) {
		if(!sysUtil.isArray(value)) {
			value = value.trim().split(',');
		}
		if(this.$fields && this.$fields.length) {
			this.$fields = this.$fields.concat(value);
		}
		else {
			this.$fields = value;
		}
	}

	return this;
};


/**
 * 设置要排除的查询字段
 * @param  Array   $fields 要排除的字段数组
 * @param  boolean $merge  是否合并现有参数, 默认为合并
 * @return Object          返回当前数据中心对象供链式调用
 */

DataCenterHelper.prototype.excludeFields = function(value, merge) {
	if(merge === undefined) {
		merge = true;
	}
	if(value) {
		if(!Array.isArray(value)) {
			value = value.trim().split(',');
		}

		if(!this.$excludeFields || !this.$excludeFields.length || !merge) {
			this.$excludeFields = value;
		}
		else {
			this.$excludeFields = this.$excludeFields.concat(value);
		}
	}

	return this;
};


/**
 * 过滤是否不查询指标统计数据
 * @param  Mix    $no_stastic <可选> 设置是否不查询统计数据, 默认从参数中读取
 * @param  string $param_name <可选> 查询字段参数变量名, 默认为 no_stastic_data
 * @return Object             返回当前数据中心对象供链式调用
 */

DataCenterHelper.prototype.filterNoStasticData = function(noStastic, name) {
	if(noStastic === undefined) {
		noStastic = this.get(name || 'no_stastic_data', 0);
	}

	this.PARAM.noMetrics(noStastic);
	return this;
};

/*
	过滤指标项.
	value true 时就调用配置的默认metrics 字段
	value false 时就不查指标数据 (默认的情况)
	value ['c','b'] 或者 'c,b' 就只查c b 指标.
 */
DataCenterHelper.prototype.filterMetricsField = function(value, name) {
	if(!value) {
		value = this.get(name || 'metrics');
	}

	this.PARAM.metricField(value);
	return this;
};


/**
 * 过滤排序参数
 * @param  Mix    $order      <可选> 指定排序参数, 默认为从参数中读取
 * @param  string $param_name <可选> 排序参数变量名, 默认为 order
 * @return Object             返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.filterOrder = function(value, name) {
	if(value === false) {
		this.PARAM.order('');
		return this;
	}
	if(!value) {
		value = this.get(name || 'order');
		if(!value) {
			value = this.get('sort');
		}
	}
	if(!value) {
		return this;
	}

	if(sysUtil.isString(value)) {
		var list = value.split(',');
		value = {};
		list.forEach(function(v) {
			var obj = v.split('|');
			value[obj[0]] = +obj[1];
		});
	}

	this.PARAM.order(value);
	return this;
};

/**
 * 过滤分页参数
 * @param  integer $page <可选> 当前页码, 默认为 1
 * @param  integer $size <可选> 分页大小, 默认为 20
 * @return Object        返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.filterPage = function(page, size) {
	if(!page && !size && this.get('no_limit')) {
		this.PARAM.page(0);
		this.PARAM.size(0);
	}
	else {
		if(page === undefined) {
			page = this.get('page', -1, 'int');
		}
		if(size === undefined) {
			size = this.get('limit', -1, 'int');
			if(size < 0) {
				size = this.get('size', -1, 'int');
			}
		}

		if(+page >= 0) {
			this.PARAM.page(+page);
		}
		if(+size >= 0) {
			this.PARAM.size(+size);
		}

	}

	return this;
};

// 修改查询结果的返回类型
DataCenterHelper.prototype.filterQuery = function(type, field) {
	if(!type) {
		var value = this.get(field || 'noAmount', false, 'bool');
		if(value) {
			type = 'items';
		}
	}
	this.PARAM.query(type || 'items,amount');
	return this;
};

// 添加查询参数与条件, 参数形式参照 DataCenterParam::add_and()
DataCenterHelper.prototype.filterAnd = function() {
	this.PARAM.addAnd.apply(this.PARAM, arguments);
	return this;
};

// 删除指定名称的 AND 过滤参数, 并返回原始过滤条件
DataCenterHelper.prototype.removeAnd = function(name) {
	return this.PARAM.removeAnd(name);
};

// 获取指定名称的 AND 过滤参数条件
DataCenterHelper.prototype.getAnd = function(name) {
	return this.PARAM.getAnd(name);
};

// 返回指定的指标过滤条件
DataCenterHelper.prototype.getCond = function(name) {
	return this.PARAM.getCond(name);
};

// 添加查询参数或条件, 参数形式参照 DataCenterParam::add_or()
DataCenterHelper.prototype.filterOr = function() {
	this.PARAM.addOr.apply(this.PARAM, arguments);
	return this;
};

// 删除指定名称的 or 过滤参数, 并返回原始过滤条件
DataCenterHelper.prototype.removeOr = function(name) {
	return this.PARAM.removeOr(name);
};

// 获取指定名称的 or 过滤参数条件
DataCenterHelper.prototype.getOr = function(name) {
	return this.PARAM.getOr(name);
};

// 要求go查询返回所有空字段记录
DataCenterHelper.prototype.fullRecord = function(stat) {
	this.PARAM.fullRecord(stat);
	return this;
};

// 设置keys 维度, 数组
DataCenterHelper.prototype.setKeys = function(value) {
	this.PARAM.setKeys(value);
	return this;
};

// 设置must_key 的值,优先级最高
DataCenterHelper.prototype.mustKeys = function(value) {
	this.PARAM.mustKeys(+value);
	return this;
};

// 设置是否优先查Go,优先级最高
DataCenterHelper.prototype.queryByGo = function(value) {
	this.PARAM.queryByGo(!!value);
	return this;
};

// 设置是否优先查Go 的amount,优先级最高
DataCenterHelper.prototype.amountByGo = function(value) {
	this.PARAM.amountByGo(!!value);
	return this;
};

// 获取返回参数对象
DataCenterHelper.prototype.getParam = function() {
	return this.PARAM;
};

// 返回最后一次查询的错误代码
DataCenterHelper.prototype.getError = function(output) {
	return this.$errorCode;
};

// 返回最后一次查询的结果, 包含debug信息
DataCenterHelper.prototype.getErrorMessage = function(value) {
	if(value === true) {
		return this.$errorData;
	}
	return this.$errorData['message'];
};

/**
 * 过滤统计数据查询条件
 * @param  string  $cond       <可选> 指定指标统计过滤条件, 默认为从请求参数中读取
 * @param  boolean $append     <可选> 是否附加条件, 默认为真 ,追加
 * @param  string  $param_name <可选> 参数名字, 默认为 condition
 * @return Object              返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.filterCondition = function(value, append, name) {
	if(append === undefined) {
		append = true;
	}
	if(name === undefined) {
		name = 'condition';
	}
	if(!value) {
		value = this.get(name);
	}

	if(value) {
		this.PARAM.addCond(value, append);
	}

	return this;
};

/**
 * 统计数据附加过滤查询条件
 * @param  string  $cond       <可选> 过滤条件名称, 为false时清除过滤条件
 * @param  mix     $append     <可选> 过滤条件参数
 * @return Object              返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.filterDimCondition = function(name, value) {
	if(name === false) {
		this.$dimCond = {};
	}
	else if(sysUtil.isObject(name)) {
		util.extend(this.$dimCond, name);
	}
	else if(value === undefined) {
		if(this.$dimCond[name]) {
			delete this.$dimCond[name];
		}
		else {
			return this;
		}
	}
	else {
		this.$dimCond[name] = value;
	}

	this.PARAM.addDimCond(this.$dimCond, false);
	return this;

};

/**
 * 统计数据附加过滤查询条件
 * @param  string  $cond       <可选> 过滤条件名称, 为false时清除过滤条件
 * @param  mix     $append     <可选> 过滤条件参数
 * @return Object              返回当前数据中心对象供链式调用
 */

DataCenterHelper.prototype.filterAddOnCondition = function(name, value) {
	if(name === false) {
		this.$addOnCond = {};
	}
	else if(sysUtil.isObject(name)) {
		sysUtil.extend(this.$addOnCond, name);
	}
	else if(value === undefined) {
		if(this.$addOnCond[name]) {
			delete this.$addOnCond[name]
		}
		else {
			return this;
		}
	}
	else {
		this.$addOnCond[name] = value;
	}

	this.PARAM.addAddOnCond(this.$addOnCond, false);
	return this;
};

// 查询_id为0的默认数据。
DataCenterHelper.prototype.filterZero = function(name, field){
	name = name || '默认';
	this.PARAM.filterZero(name, field);
}

/**
 * 过滤标签条件
 * @param  string  $param_name <可选> 标签过滤参数名称, 默认为 Labels, 可取为字符串以,分隔或直接数组格式.
 * @param  boolean $all        <可选> 是否要包含所有标签条件
 * @return Object              返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.filterLabel = function(paramName, fieldName, all) {
	var labels = this.get(paramName || 'Labels', '');
	if(sysUtil.isString(labels) && labels.length) {
		labels = labels.split(',');
	}
	else if(!sysUtil.isArray(labels)) {
		labels = null;
	}
	if(labels && labels.length) {
		var cond = {};
		cond[all ? '$all': '$in'] = labels;
		this.PARAM.addAnd(fieldName || 'Labels', cond);
	}

	return this;
};

DataCenterHelper.prototype.filterOwner = generator(function*(filterStatic) {
	var self = this;
	var user = yield include.getUser();
	var uid = user.getCurrentId();
	var field = config('querys.'+ self.$type + '.owner_model_key');
	if (!field){
		field = config('keys.owner_model');
	}
	if (field){
		self.PARAM.addAnd(field, uid);
	}
	if (filterStatic){
		field = config('querys.'+ self.$type + '.owner_statistics_key');
		if (!field){
			field = config('keys.owner_statistics');
		}
		if (field){
			self.filterAddOnCondition(field, uid);
		}
	}

	return self;
});

/**
 * 过滤记录所有人
 * @param  mix     $creator <可选> 所有人过滤参数, UserId 或 UserId 数组,
 *                          -1 表示查看所有账户, 默认为当前激活用户
 * @param  integer $master  <可选> 控制可查看 UserId 的起始 UserId,
 *                          限定为某一个代理账号, 则只能查看其子客户,
 *                          默认为当前激活用户
 * @param  boolean $childs  <可选> 是否包含子客户账号, 默认不包含
 * @param  boolean $all     <可选> 是否包含已删除账号, 默认不包含
 * @return Object           返回当前数据中心对象供链式调用
 */

DataCenterHelper.prototype.filterCreator = generator(function*(creator, master, childs, all) {
	var self = this;
	var creatorIsArray;
	var user = yield include.getUser();
	if(creator === undefined) {
		creator = 0;
	}
	if(master === undefined) {
		master = 0;
	}

	if(master <= 0) {
		master = user.cid();
	}

	creatorIsArray = Array.isArray(creator);
	if(!creatorIsArray && !creator) {
		creator = user.cid();
	}

	if(all && user.isMaster()) {
		//超级账号可查看任何账号, 并且查看所有状态的账号
		if(!creatorIsArray) {
			if(creator > 0) {
				creator = [creator];
			}
			else {
				creator = false;
			}
		}
	}
	else {
		//非超级账号或只查看有效账号
		if(creatorIsArray) {
			if(creator.length) {
				creator = util.intersection(creator, (yield getOwnUserId.call(self, master, all)));
			}
			else {
				creator = false;
			}
		}
		else if(creator <= 0) {
			childs = false; // 已包含所有子客户, 无需再查询
			creator = yield getOwnUserId.call(self, master, all);
		}
		else {
			creator = [+creator];
		}
	}

	if(creator === false) {
		return;
	}

	if(childs && creator) {
		// 查询子账户
		var query = {
			'CreateUserId': {'$in': creator}
			,'Type': {'$ne': CONST.USER_TYPE_EMPLOYEE}
		};

		if(!all) {
			query.IsDeleted = false;
		}
		let cids = yield self.$dataCenterGo.findAll(hawkConfig.user_model, {query: query}, idField);
		if(cids.length) {
			creator = util.unique(creator.concat(cids));
		}
	}

	if(creator.length === 1) {
		self.PARAM.addAnd('CreateUserId', creator[0]);
	}
	else {
		self.PARAM.addAnd('CreateUserId', '$in', creator);
	}
});

/**
 * 按照搜索关键字过滤用户记录
 * @param  String  $word   <可选> 搜索的用户名称关键字, 空格分隔多个条件, 默认为请求参数 Word
 * @param  boolean $childs <可选> 是否包含子客户账号, 默认不包含
 * @param  boolean $all    <可选> 是否搜索所有用户, 包括已删除用户
 * @return Object          返回当前数据中心对象供链式调用
 */

DataCenterHelper.prototype.filterCreatorWord = generator(function*(word, childs, all) {
	var self = this;
	if(!word) {
		word = self.get('word','', 'trim');
	}
	if(word) {
		var user = yield include.getUser();
		var regx = getMongoRegx(word);
		var query = new MongoCriteria();
		query.filterAnd('Type', '$ne', CONST.USER_TYPE_EMPLOYEE);
		var tmp = {};
		tmp[idField] = regx;
		query.filterOr([{'Name': regx}, tmp]);
		query.filterAnd('CreateUserId', user.cid());
		var ids = yield self.$dataCenterGo.findAll(hawkConfig.user_model, {query: query.getQuery()}, idField);
		yield self.filterCreator(ids, 0, childs, all)
	}
	else {
		yield self.filterCreator(-1, 0, childs, all);
	}

	return self;
});


/**
 * 按照请求参数过滤显示指定公司记录
 * @param  integer $creator <可选> 默认查询的用户ID, 默认为当前作用账号
 * @param  boolean $childs  <可选> 是否包含子客户账号, 默认不包含
 * @param  boolean $all     <可选> 是否显示所有账户, 包括已删除账号
 * @return Object           返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.filterCreatorParam = function(creator, childs, all) {
	var self = this;
	return util.promise(function(ok, fail) {
		var userId = self.get('UserId', 0, 'int');
		//现在已经没有公司id这一概念,统一 '_id'
		if(userId > 0) {
			creator = userId;
		}

		self.filterCreator(creator, 0, childs, all).then(ok, fail);
	});
};

/**
 * 过滤统计数据时间段, 默认统计当天开始和结束
 * @return Object 返回当前数据中心对象供链式调用
 */
DataCenterHelper.prototype.filterStaticTime = function() {
	if(this.get('stastic_all_time',0) == 1) {
		this.PARAM.begin(0);
		this.PARAM.end(0);
	}
	else {
		var begin = this.get('begindate',0);
		if(begin) {
			this.PARAM.begin(begin);
		}
		var end = this.get('enddate',0);
		if(end) {
			this.PARAM.end(end);
		}
	}

	return this;
};

/**
 * 除了match的其它聚合渠道条件.
 */
DataCenterHelper.prototype.filterAggregate = function(param) {
	if(param){
		if(!sysUtil.isArray(param)) {
			param = [param];
		}

		this.PARAM.aggregate(param);
	}

	return this;
};

/**
 * 设定起始时间
*/
DataCenterHelper.prototype.setStaticTime = function(begindate, enddate) {
	begindate = parseInt(begindate) === begindate ? begindate : 0;
	enddate   = parseInt(enddate) === enddate ? enddate : 0;

	this.PARAM.begin(begindate);
	this.PARAM.end(enddate);
	return this;
};

DataCenterHelper.prototype.getFields = function() {
	return Array.isArray(this.$fields) ? this.$fields : [];
};

DataCenterHelper.prototype.skipMetricCheck = function(v) {
	this.PARAM.skipMetricCheck(v);
	return this;
};

/**
 * 查询并返回查询结果数组
 * @param  Boolean $res    <可选> 是否直接输出查询结果, 默认为返回结果
 * @return Array           返回查询结果数组
 */
DataCenterHelper.prototype.query = function*() {
	var self = this;
	var debug = self.get('debug', 0, 'int');
	var datacenter = self.$dataCenterGo;
	var opts = self.getOptions();
	if(!opts.base)
	{
		opts.base = {};
	}

	opts.base.timeout = hawkConfig.timeout || 300000;
	datacenter.debug(debug);
	return yield datacenter.query(opts);
};

var standardExportCallback = function*(type, data, param, helper) {
	switch (type) {
		case 'file':
			var fn = '';
			if(helper && helper.getParam) {
				var p = helper.getParam();
				var start = new Date(p.begin() * 1000);
				var end = new Date(p.end() * 1000);
				start = util.date('Ymd',start);
				end = util.date('Ymd', end);
				fn = param['name'] + start + '-' + end;
			}
			else {
				fn = param.name;
			}

			return fn;
		case 'head':
			return Array.isArray(param['title']) ? param['title'] : [param['title']];
		case 'item':
			var field = param['main_field'];
			if(Array.isArray(field)) {
				//这里感觉怪怪的
				var result = [];
				field.forEach(function(name) {
					result.push(data.hasOwnProperty(name) ? data[name] : '—');
				});

				return result;
			}
			else {
				return [data[field] ? data[field] : '—'];
			}
		default :
			return;
	}
};

/**
 * 导出csv报表文件
 * @param  function $callback       格式化行数据函数, fn(type, row, param), type=file/head/item
 * @param  function $callback_param <可选> 格式化函数附加参数, 通过回调函数第三个参数提供
 * @param  function $res  			response 用于设置回复的header之类的.
 */

exports.export = function*(callback, callbackParam, data, isOffline) {
	var self = this;
	//偏移去掉callbackParam
	if(arguments.length == 3)
	{
		isOffline = data;
		data = callbackParam;
		callbackParam = null;
	}

	var output = [];
	var result = data;
	var param = ['file', result, callbackParam, self];
	var exFunc;
	if(sysUtil.isFunction(callback)) {
		exFunc = callback;
	}
	else {
		exFunc = standardExportCallback;
	}

	var fileName = yield exFunc.apply(self, param);
	output.push(yield exportOutputHeader.call(self, fileName, isOffline));
	// 整理指标列字段
	param[0] = 'cols';
	var cols = yield exFunc.apply(self, param);
	if(!Array.isArray(cols)) {
		cols = callbackParam && callbackParam.first_cols || [];
	}
	if(result.amount) {
		cols = cols.concat(util.keys(result.amount));
	}
	else if(result.items && result.items[0]) {
		var tmpCols = util.keys(result.items[0]);
		var metricCols = [];
		tmpCols.forEach(function(col) {
			if(isMetric(col)) {
				metricCols.push(col);
			}
		});

		cols = cols.concat(metricCols);
	}

	cols = util.unique(cols);
	// 转换指标名称为标题名称
	param[0] = 'head';
	var head = yield exFunc.apply(self, param);
	var headCount = head.length;
	var captions = config('captions') || {};
	cols.forEach(function(key) {
		head.push( captions[key] ? captions[key] : key);
	});

	output.push(exportOutputRow(head));
	// 转换汇总行数据
	if(result.amount) {
		var total = (result.items && result.items.length) || 0;
		var amount = exportFormatRow(result.amount);
		var row = [];

		for(var i = 0; i < headCount; i++) {
			row[i] = '';
		}
		row[0] = include.LANG('合计:共%1条', total);

		cols.forEach(function(key) {
			row.push(amount[key] !== undefined ? amount[key] : '—');
		});

		output.push(exportOutputRow(row));
	}

	// 转换数据记录
	if(result.items) {
		var items = exportFormatRow(result['items']);
		for(var i = 0; i < items.length; i++) {
			let item = items[i];
			let key = i;
			row = yield exFunc.apply(self, ['item', item, callbackParam]);
			items[key] = exportFormatRow(item);
			cols.forEach(function(k) {
				row.push(items[key][k] !== undefined ? items[key][k] : '—');
			});

			output.push(exportOutputRow(row));
		}
	}

	if(isOffline)
	{
		return {
			Name: fileName
			,buf: Buffer.concat(output)
		};
	}

	return Buffer.concat(output);
};

DataCenterHelper.prototype.export = function*(callback, callbackParam) {
	var self = this;
	var opts = self.getOptions();
	opts.base.timeout = hawkConfig.export_timeout || 3600000;
	var result = yield self.$dataCenterGo.query(opts);
	var args = Array.prototype.slice.call(arguments);
	args.push(result);
	args.push(false);
	return yield exports.export.apply(self, args);
};

DataCenterHelper.prototype.offline_export = function*(callback, callbackParam) {
	var self = this;
	var opts = self.getOptions();
	var result = yield self.$dataCenterGo.query(opts);
	return yield exports.export.apply(self, [callback, callbackParam, result, true]);
};

/**
 * 格式化行记录指标格式
 * @param  object row 原始数据行数据对象
 * @return Array      返回格式化后的数据行数据数组
 */
var format_fn = {
	rate: function(value) {
		return (+value * 100).toFixed(3) + '%';
	}
	,rate2: function(value) {
		return (+value / 100).toFixed(3) + '%';
	}
	,second: function(value) {
		return value + '秒';
	}
	,millitosecond: function(value) {
		return value/1000 + '秒';
	}
	,time: function(value) {
		var nums = ['0', '00', '00'];
		// 提取秒
		var mod = value % 60;
		nums[2] = ('0'+ mod).substr(-2);
		// 提取分
		value -= mod;
		mod = value % 60;
		nums[1] = ('0'+ mod).substr(-2);
		// 提取小时
		nums[0] = value - mod;
		return nums.join(':');
	}
};
var format_map;
function exportFormatRow(row){
	var self = this;
	if (!format_map) {
		format_map = config('formats');
	}

	if(sysUtil.isObject(format_map)) {
		var value;
		for(var key in row) {
			if(row.hasOwnProperty(key)) {
				value = row[key];
				var format = format_map[key];
				if(format && format_fn[format]) {
					row[key] = format_fn[format].call(self, value);
				}
			}
		}
	}
	return row;
}

var exportOutputHeader = util.generator(function*(filename, isOffline) {
	if(!isOffline)
	{
		filename = encodeURIComponent(filename);
		var res = radon.getContextData('response');
		res.setHeader('Content-type', 'text/csv; charset=utf8');
		res.setHeader('Content-Disposition', 'attachment; filename="' + filename + '.csv"');
		res.setHeader('Cache-Control', 'must-revalidate,post-check=0,pre-check=0');
		res.setHeader('Expires', 0);
		res.setHeader('Pragma', 'public');
	}

	return new Buffer([0xef,0xbb, 0xbf]);
});

function exportOutputRow(row){
	var result = '';

	row.forEach(function(value) {
		result += (result ? ',': '');
		if(sysUtil.isString(value)) {
			if(!isNaN(+value)) {
				result += '"=""' + value + '"""';
			}
			else if(value){
				var old = value;
				//" => ""  , \n , 都要"" 括住.
				value = value.replace(/\"/g, '""');
				if('=+-'.indexOf(value[0]) !== -1) {
					result += '"="' + value + '""';
				}
				else if(old != value || value.match(/,|\n/)) {
					//表示是否发生过替换.
					result += '"' + value + '"';
				}
				else {
					result += value;
				}
			}
		}
		else if(value > 0x7fffffff) {
			result += '"=""' + value + '"""';
		}
		else {
			result += value;
		}
	});

	return new Buffer(result + "\r\n");
}

var numberRegx = /^\d+$/;
var _64Regx = /^\#\w+$/;
// 获取变量的逗号分隔 ID 变量数组
function getParamIds(paramName, delimiter) {
	var ids = this.get(paramName, '', 'trim');
	var list = [];
	if(ids) {
		if(sysUtil.isString(ids)) {
			ids = ids.split(delimiter || ',');
		}

		var id;
		while(id = ids.shift()) {
			if (numberRegx.test(id) || _64Regx.test(id)) {
				list.push(include.Number(id));
			}
		}
	}

	return list;
}

/**
 * 转换时间变量为该天开始的 Unix TimeStamp
 * @param  Mix     $time 时间变量, 8位日期数字或日期字符串或Timestamp整数
 * @return Integer       返回转换后的 Unix Timestamp 整数
 */
function toDateStamp(time) {
	if(isNaN(+time)) {
		time = new Date(time).getTime();
	}
	else {
		time = +time;
	}
	if(time > 0) {
		var diff = this.PARAM.$timeZone;
		time -= (time - diff) % 86400;
	}

	return time;
}

// 返回查看的用户ID列表
var user_cache = {};
var getOwnUserId = generator(function*(userId, all) {
	var self = this;
	var _conf = user_cache[userId];
	// 有缓存，并且未过期
	if(!_conf || _conf.time < Date.now())
	{
		//查询用户下所有的用户ID
		var allList = [];
		var normalList = [userId];
		var queue = [userId];
		var query = {
			'Type': {'$ne': CONST.USER_TYPE_EMPLOYEE} //非员工账号
		};

		var users;
		while(queue && queue.length) {
			allList = allList.concat(queue);
			query.CreateUserId = {'$in': queue};
			users = yield self.$dataCenterGo.findAll(hawkConfig.user_model, {query: query});
			queue = [];
			if(users && users.length) {
				users.forEach(function(u) {
					if(u.isDeleted === false || u.IsDeleted === false) {
						normalList.push(u[idField]);
					}
					queue.push(u[idField]);
				});

				queue = util.difference(queue, allList);
			}
		}

		_conf = user_cache[userId] = {
			'time': Date.now() + 300000,
			'data': {
				'all': allList
				,'normal': normalList
			}
		};
	}

	return _conf.data[all ? 'all': 'normal'].slice(0);
});